﻿using System;

namespace NodeJS.stream
{
    /// <summary>
    /// The Readable stream interface is the abstraction for a source of data that you are reading from.
    /// In other words, data comes out of a Readable stream.
    /// A Readable stream will not start emitting data until you indicate that you are ready to receive it.
    /// Readable streams have two "modes": a flowing mode and a non-flowing mode. 
    /// <para>When in flowing mode, data is read from the underlying system and provided to your program as fast as possible.</para>
    /// <para>In non-flowing mode, you must explicitly call stream.read() to get chunks of data out.</para>
    /// </summary>
    [ImportClass("", "require('stream').Readable")]
    public class Readable : EventEmitter, IReadable
    {
        /// <summary>
        /// In classes that extend the Readable class, make sure to call the Readable constructor so that the buffering settings can be properly initialized.
        /// </summary>
        /// <param name="options">options Object
        /// <para>highWaterMark Number The maximum number of bytes to store in the internal buffer before ceasing to read from the underlying resource. Default=16kb</para>
        /// <para>encoding String If specified, then buffers will be decoded to strings using the specified encoding. Default=null</para>
        /// <para>objectMode Boolean Whether this stream should behave as a stream of objects. Meaning that stream.read(n) returns a single value instead of a Buffer of size n</para>
        /// </param>
        public Readable(object options = null)
        {
        }

        /// <summary>
        /// When a chunk of data can be read from the stream, it will emit a 'readable' event.
        /// Once the internal buffer is drained, a readable event will fire again when more data is available.
        /// </summary>
        [EvalAtCompile(Value = "readable")]
        public const NodeEvent READABLE = null;

        /// <summary>
        /// If you attach a data event listener, then it will switch the stream into flowing mode, and data will be passed to your handler as soon as it is available.
        /// If you just want to get all the data out of the stream as fast as possible, this is the best way to do so.
        /// </summary>
        [EvalAtCompile(Value = "data")]
        public const NodeEvent<StringOrBuffer> DATA = null;
        

        /// <summary>
        /// This event fires when no more data will be provided.
        /// Note that the end event will not fire unless the data is completely consumed. This can be done by switching into flowing mode, or by calling read() repeatedly until you get to the end.
        /// </summary>
        [EvalAtCompile(Value = "end")]
        public const NodeEvent END = null;

        /// <summary>
        /// Emitted when the underlying resource (for example, the backing file descriptor) has been closed. Not all streams will emit this.
        /// </summary>
        [EvalAtCompile(Value = "close")]
        public const NodeEvent CLOSE = null;

        /// <summary>
        /// Emitted if there was an error receiving data.
        /// </summary>
        [EvalAtCompile(Value = "error")]
        public const NodeEvent ERROR = null;

        public virtual StringOrBuffer Read(int size = 0)
        {
            return null;
        }

        public virtual void SetEncoding(Encoding encoding)
        {
        }

        public virtual void Resume()
        {
        }

        public virtual void Pause()
        {
        }

        public virtual IWritable Pipe(IWritable destination, object options = null)
        {
            return null;
        }

        public virtual void Unpipe(IWritable destination = null)
        {
        }

        public virtual void Unshift(StringOrBuffer chunk)
        {
        }
    }
}
